<?php

/**
 * Framework Dat@ctiv
 *
 * @author		Mathieu Rey
 * @copyright	Copyright (c) 2008, datactiv.fr
 * @link		http://www.datactiv.fr
 */

/**
 * Cryptage
 *
 * Cette classe offre des fonctionnalités de (dé)cryptage simple et avancé
 *
 * @author		Mathieu Rey
 */

/**
 *                     TODO
 *
 * - réécrire les sorties des fonctions getinfos / choixalgo, pour utiliser des tableaux et eviter les explode
 * - voir pour stocker les clés ailleurs que dans la classe
 * - faire que les fonctions getinfos / choixalgo soient privées
 */
 
/*
// ------------------

error_reporting("E^ALL");
set_error_handler('_exception_handler');

function _exception_handler($severity, $message, $filepath, $line){
	echo "<br /><b>".$severity." : </b> ".$message." (fichier : ".$filepath.", ligne : ".$line.")<br /><br />";
}

// ------------------
*/
class Crypt{

	private $simple_cle = "arempliretnejamaischanger";
	private $simple_iv =  "arempliretnejamaischangernonplus"; 

	
	function __construct(){
		
	}
	
	/**
	 * scypt
	 * 
	 * Méthode de cryptage simple (clé, IV, algorithme et mode figés)
	 */
	function scrypt($content){

		// Remarque
		// --------
		// On ajoute un sel, invariant, avant le md5 afin d'améliorer la sécurité
		// En effet, il est potentiellement possible d'accéder de manière non autorisée à simple_cle et simple_iv 
		// (via un var_dump de l'objet par exemple)

		// Reconstitution de la clef de cryptage et de l'IV
		$cle = md5($this->simple_cle."^;)àé'(-_è'('-(654/*-2");
		$iv = md5("ç)è_àç_àùç_^)ç_àç_ùà/*/".$this->simple_iv);

		$td = mcrypt_module_open ("rijndael-256", "", "ofb", "");
		mcrypt_generic_init ($td, $cle, $iv);

		$quoi = mcrypt_generic ($td, $content);
		mcrypt_generic_deinit ($td);

		return base64_encode($quoi);

	}

	/**
	 * unscrypt
	 * 
	 * Méthode de décryptage associée à scrypt
	 */
	function unscrypt($content){

		$cle = md5($this->simple_cle."^;)àé'(-_è'('-(654/*-2");
		$iv = md5("ç)è_àç_àùç_^)ç_àç_ùà/*/".$this->simple_iv);

		$td = mcrypt_module_open ("rijndael-256", "", "ofb", "");
		mcrypt_generic_init ($td, $cle, $iv);

		$content = base64_decode($content);
		$quoi = mdecrypt_generic ($td, $content);
		mcrypt_generic_deinit ($td);

		return $quoi;

	}

	/**
	 * crypter
	 * 
	 * Méthode de cryptage variable (choix aléatoire d'un modèle)
	 */
	function crypter($quoi){
		
		// On choisit aléatoirement un modèle
		$monalgo = $this->choisiralgo();
		$paramsalgo = explode("#", $this->getdetailsalgo($monalgo));

		// Cryptage
		$td = mcrypt_module_open ($paramsalgo[0], "", $paramsalgo[3], "");
		mcrypt_generic_init ($td, $paramsalgo[1], $paramsalgo[2]);
		$quoi = mcrypt_generic ($td, $quoi);
		mcrypt_generic_deinit ($td);

		return base64_encode($monalgo."<<<".$quoi);

	}

	/**
	 * uncrypter
	 * 
	 * Méthode de décryptage associée à crypter
	 */
	function uncrypter($quoi){

		$quoi = base64_decode($quoi);

		// On récupère les informations sur le modèle
		$parts = explode("<<<", $quoi);
		$paramsalgo = explode("#", $this->getdetailsalgo($parts[0]));

		// Décryptage
		$td = mcrypt_module_open ($paramsalgo[0], "", $paramsalgo[3], "");
		mcrypt_generic_init ($td, $paramsalgo[1], $paramsalgo[2]);
		$quoi = mdecrypt_generic ($td, $parts[1]);
		mcrypt_generic_deinit ($td);

		return rtrim($quoi);

	}


	/**
	 * getdetailsalgo
	 * 
	 * Renvoie la clé, l'IV, le mode et l'algorithme à utiliser pour un modèle donné
	 */
	function getdetailsalgo($arg){

		$algo = array();

		// Remarque importante
		// -------------------
		// Il est important de ne JAMAIS supprimer une ligne dans ce qui suit
		// Cela compromettrait définitivement toute lecture des données encodées avec le modèle en question

		$algo["abcdef"] = "cast-128#f4f4f5gueyghrgft#9xer5rrc";

		$modes = array("cbc", "ofb", "cfb", "ecb");

		$arg1 = substr($arg, 0, 6);
		$arg2 = substr($arg, -1, 1);
		
		return $algo[$arg1]."#".$modes[$arg2];

	}

	/**
	 * choisiralgo
	 * 
	 * Choisit aléatoirement un modèle
	 */
	function choisiralgo(){

		// Remarque importante
		// -------------------
		// Contrairement à la fonction getdetailsalgo(), il est possible de supprimer des 
		// entrées dans le tableau qui suit. Ceci aura pour effet d'arrêter d'utiliser le modèle en question
		// pour encoder les nouvelles données, mais celles déjà encodées avec ce modèle restent décryptables
		// car la définition du modèle est toujours présente dans getdetailsalgo()

		$listealgos = array("abcdef");

		return $listealgos[rand(0, count($listealgos)-1)].rand(0, 3);

	}

}

/*

Exemple d'utilisation
---------------------


$c = new Crypt();

// Test des fonctions de la class Crypt
echo "<h1>Test des fonctions de la classe Crypt</h1>";

$machaine = "J'aime les pâtes à la carbonara !";
echo "Chaine d'exemple : ".$machaine."<br /><br /><u>Cryptage simple</u><br />Phrase cryptée : ";
$chaine = $c->scrypt($machaine);
echo $chaine."<br />Après base64_decode : ".base64_decode($chaine)."<br />Décryptée : ".$c->unscrypt($chaine);

echo "<br /><br /><u>Cryptage variable</u><br />Phrase cryptée : ";
$chaine = $c->crypter($machaine);
echo $chaine."<br />Après base64_decode : ".base64_decode($chaine)."<br />Décryptée : ".$c->uncrypter($chaine);

// Test des modes et algorithmes disponibles sur le système
echo "<h1>Test des algorithmes et modes disponibles sur le système</h1>";

$tmode = array("cbc", "ofb", "cfb", "ecb");

$talgo = array("cast-128", "gost", "rijndael-128", "cast-256", "loki97", "rijndael-192", "blowfish-compat", "des", "rijndael-256", "serpent", "xtea", "rc2", "tripledes");	

$bg = "";
foreach ($talgo as $algo){

	if ($bg == "#eaeaea") $bg = "#dedede"; else $bg = "#cacaca";

	echo "<div style='margin: 8px; float: left; width: 150px; display: block; background-color: ".$bg.";'>Algo <b>".$algo."</b><br />";

	foreach ($tmode as $mode){

		echo "Mode ".$mode." -&gt; ";

		if ($td = mcrypt_module_open ($algo, "", $mode, ""))
			echo '<font color="#00ff00">OK</font><br />';
		else
			echo '<font color="#ff0000">FAIL</font><br />';

	}

	echo "</div>";

}
*/
?>